<template>
  <div
    class="nebula-button-container"
    :class="{
      'disabled': disabled,
      'loading': loading,
      'has-icon': iconLeft || iconRight
    }"
    ref="buttonContainerRef"
  >
    <!-- 粒子效果背景 -->
    <div class="particle-background" ref="particleRef"></div>
    
    <!-- 按钮内容 -->
    <button
      :disabled="disabled || loading"
      @click="handleClick"
      @mouseenter="handleMouseEnter"
      @mouseleave="handleMouseLeave"
      :class="[
        'nebula-button',
        variant,
        size,
        { 'pulsing': isPulsing }
      ]"
      :style="buttonStyle"
    >
      <!-- 左侧图标 -->
      <div v-if="iconLeft" class="button-icon left-icon">
        <slot name="left-icon"></slot>
      </div>
      
      <!-- 加载状态 -->
      <div v-if="loading" class="loading-spinner">
        <div class="spinner"></div>
      </div>
      
      <!-- 按钮文本 -->
      <span v-else class="button-text" :class="{ 'has-icons': iconLeft && iconRight }">
        {{ text }}
      </span>
      
      <!-- 右侧图标 -->
      <div v-if="iconRight" class="button-icon right-icon">
        <slot name="right-icon"></slot>
      </div>
    </button>
  </div>
</template>

<script>
import { ref, onMounted, onUnmounted, computed } from 'vue'
import * as THREE from 'three'

export default {
  name: 'NebulaButton',
  props: {
    text: {
      type: String,
      required: true
    },
    variant: {
      type: String,
      default: 'primary',
      validator: (value) => ['primary', 'secondary', 'outline', 'text'].includes(value)
    },
    size: {
      type: String,
      default: 'medium',
      validator: (value) => ['small', 'medium', 'large'].includes(value)
    },
    disabled: {
      type: Boolean,
      default: false
    },
    loading: {
      type: Boolean,
      default: false
    },
    iconLeft: {
      type: Boolean,
      default: false
    },
    iconRight: {
      type: Boolean,
      default: false
    },
    pulse: {
      type: Boolean,
      default: false
    },
    particleEffect: {
      type: Boolean,
      default: true
    },
    // 自定义颜色
    primaryColor: {
      type: String,
      default: '#5588ff'
    },
    secondaryColor: {
      type: String,
      default: '#1e3a8a'
    }
  },
  emits: ['click'],
  setup(props, { emit }) {
    const buttonContainerRef = ref(null)
    const particleRef = ref(null)
    const isPulsing = ref(false)
    const mouseOver = ref(false)
    
    // Three.js相关变量
    let scene = null
    let camera = null
    let renderer = null
    let particles = null
    let animationId = null
    let mousePosition = { x: 0, y: 0 }
    let particlesGeometry = null
    let particlesMaterial = null
    
    // 计算按钮样式
    const buttonStyle = computed(() => {
      const baseStyle = {
        '--primary-color': props.primaryColor,
        '--secondary-color': props.secondaryColor
      }
      
      return baseStyle
    })
    
    // 处理点击事件
    const handleClick = (event) => {
      if (props.disabled || props.loading) return
      
      // 创建点击粒子爆炸效果
      createExplosionEffect()
      
      emit('click', event)
    }
    
    // 处理鼠标进入
    const handleMouseEnter = () => {
      mouseOver.value = true
      
      if (props.pulse) {
        isPulsing.value = true
      }
      
      // 增加粒子速度
      if (particles) {
        particles.userData.speed = 0.015
        particles.userData.attraction = 0.1
      }
    }
    
    // 处理鼠标离开
    const handleMouseLeave = () => {
      mouseOver.value = false
      
      if (props.pulse) {
        isPulsing.value = false
      }
      
      // 减少粒子速度
      if (particles) {
        particles.userData.speed = 0.005
        particles.userData.attraction = 0
        mousePosition.x = 0
        mousePosition.y = 0
      }
    }
    
    // 创建粒子背景
    const createParticleEffect = () => {
      if (!props.particleEffect || !particleRef.value) return
      
      const rect = particleRef.value.getBoundingClientRect()
      
      // 创建场景
      scene = new THREE.Scene()
      
      // 创建正交相机
      camera = new THREE.OrthographicCamera(
        rect.width / -2,
        rect.width / 2,
        rect.height / 2,
        rect.height / -2,
        1,
        1000
      )
      camera.position.z = 100
      
      // 创建渲染器
      renderer = new THREE.WebGLRenderer({ 
        antialias: true, 
        alpha: true 
      })
      renderer.setSize(rect.width, rect.height)
      renderer.setPixelRatio(window.devicePixelRatio)
      renderer.domElement.style.position = 'absolute'
      renderer.domElement.style.top = '0'
      renderer.domElement.style.left = '0'
      renderer.domElement.style.pointerEvents = 'none'
      
      particleRef.value.appendChild(renderer.domElement)
      
      // 创建粒子
      const particleCount = 100
      particlesGeometry = new THREE.BufferGeometry()
      
      const positions = new Float32Array(particleCount * 3)
      const colors = new Float32Array(particleCount * 3)
      const sizes = new Float32Array(particleCount)
      
      // 解析主色和次色
      const primaryColor = new THREE.Color(props.primaryColor)
      const secondaryColor = new THREE.Color(props.secondaryColor)
      
      for (let i = 0; i < particleCount; i++) {
        const i3 = i * 3
        
        // 随机位置在按钮范围内
        positions[i3] = (Math.random() - 0.5) * rect.width * 1.5
        positions[i3 + 1] = (Math.random() - 0.5) * rect.height * 1.5
        positions[i3 + 2] = Math.random() * 100 - 50
        
        // 颜色在主色和次色之间插值
        const colorMix = Math.random()
        colors[i3] = primaryColor.r * colorMix + secondaryColor.r * (1 - colorMix)
        colors[i3 + 1] = primaryColor.g * colorMix + secondaryColor.g * (1 - colorMix)
        colors[i3 + 2] = primaryColor.b * colorMix + secondaryColor.b * (1 - colorMix)
        
        // 随机大小
        sizes[i] = 0.5 + Math.random() * 2
      }
      
      particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))
      particlesGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3))
      particlesGeometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1))
      
      // 创建材质
      particlesMaterial = new THREE.PointsMaterial({
        size: 1,
        vertexColors: true,
        sizeAttenuation: true,
        transparent: true,
        opacity: 0.6,
        blending: THREE.AdditiveBlending
      })
      
      // 创建粒子系统
      particles = new THREE.Points(particlesGeometry, particlesMaterial)
      particles.userData.speed = 0.005
      particles.userData.attraction = 0
      scene.add(particles)
      
      // 监听鼠标移动
      if (buttonContainerRef.value) {
        buttonContainerRef.value.addEventListener('mousemove', handleMouseMove)
      }
      
      // 开始动画
      animate()
    }
    
    // 处理鼠标移动
    const handleMouseMove = (event) => {
      if (!buttonContainerRef.value) return
      
      const rect = buttonContainerRef.value.getBoundingClientRect()
      const x = event.clientX - rect.left
      const y = event.clientY - rect.top
      
      // 归一化坐标 -1 到 1
      mousePosition.x = (x / rect.width) * 2 - 1
      mousePosition.y = -(y / rect.height) * 2 + 1
    }
    
    // 创建爆炸效果
    const createExplosionEffect = () => {
      if (!particles || !particlesGeometry) return
      
      const positions = particlesGeometry.attributes.position.array
      
      // 为每个粒子添加向外的速度
      for (let i = 0; i < positions.length; i += 3) {
        // 从中心向外的方向
        const dx = positions[i] * 0.1
        const dy = positions[i + 1] * 0.1
        
        // 临时存储在z坐标中作为速度
        positions[i + 2] = positions[i + 2] * 0.9 + dx
        positions[i] += dx * 2
        positions[i + 1] += dy * 2
      }
      
      particlesGeometry.attributes.position.needsUpdate = true
    }
    
    // 动画循环
    const animate = () => {
      animationId = requestAnimationFrame(animate)
      
      if (!particles || !particlesGeometry) return
      
      const positions = particlesGeometry.attributes.position.array
      const sizes = particlesGeometry.attributes.size.array
      
      // 更新粒子位置
      for (let i = 0; i < positions.length; i += 3) {
        // 旋转效果
        positions[i] = positions[i] * Math.cos(particles.userData.speed) - positions[i + 1] * Math.sin(particles.userData.speed)
        positions[i + 1] = positions[i] * Math.sin(particles.userData.speed) + positions[i + 1] * Math.cos(particles.userData.speed)
        
        // 鼠标吸引力
        if (particles.userData.attraction > 0) {
          const rect = buttonContainerRef.value?.getBoundingClientRect()
          if (rect) {
            const targetX = mousePosition.x * rect.width / 2
            const targetY = mousePosition.y * rect.height / 2
            
            positions[i] += (targetX - positions[i]) * particles.userData.attraction * 0.02
            positions[i + 1] += (targetY - positions[i + 1]) * particles.userData.attraction * 0.02
          }
        }
        
        // 粒子大小呼吸效果
        if (i / 3 % 10 === 0 && Math.random() > 0.95) {
          sizes[i / 3] = 0.5 + Math.random() * 2
          particlesGeometry.attributes.size.needsUpdate = true
        }
      }
      
      particlesGeometry.attributes.position.needsUpdate = true
      
      // 渲染
      if (renderer && scene && camera) {
        renderer.render(scene, camera)
      }
    }
    
    // 调整大小
    const handleResize = () => {
      if (!particleRef.value || !renderer || !camera) return
      
      const rect = particleRef.value.getBoundingClientRect()
      
      camera.left = rect.width / -2
      camera.right = rect.width / 2
      camera.top = rect.height / 2
      camera.bottom = rect.height / -2
      camera.updateProjectionMatrix()
      
      renderer.setSize(rect.width, rect.height)
    }
    
    // 组件挂载
    onMounted(() => {
      if (props.pulse) {
        isPulsing.value = true
      }
      
      // 延迟创建粒子效果，确保DOM已渲染
      setTimeout(() => {
        createParticleEffect()
      }, 100)
      
      // 监听大小变化
      const observer = new ResizeObserver(handleResize)
      if (particleRef.value) {
        observer.observe(particleRef.value)
      }
      
      // 清理函数
      onUnmounted(() => {
        if (observer && particleRef.value) {
          observer.unobserve(particleRef.value)
        }
      })
    })
    
    // 组件卸载
    onUnmounted(() => {
      if (animationId) {
        cancelAnimationFrame(animationId)
      }
      
      if (renderer) {
        renderer.dispose()
        if (particleRef.value && renderer.domElement) {
          particleRef.value.removeChild(renderer.domElement)
        }
      }
      
      if (particlesGeometry) {
        particlesGeometry.dispose()
      }
      
      if (particlesMaterial) {
        particlesMaterial.dispose()
      }
      
      if (buttonContainerRef.value) {
        buttonContainerRef.value.removeEventListener('mousemove', handleMouseMove)
      }
    })
    
    return {
      buttonContainerRef,
      particleRef,
      isPulsing,
      buttonStyle,
      handleClick,
      handleMouseEnter,
      handleMouseLeave
    }
  }
}
</script>

<style scoped>
.nebula-button-container {
  position: relative;
  display: inline-block;
  overflow: hidden;
  border-radius: inherit;
}

.particle-background {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  border-radius: inherit;
}

.nebula-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font-family: inherit;
  font-weight: 600;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  overflow: hidden;
  transition: all 0.3s ease;
  z-index: 1;
  background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
  color: white;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}

/* 尺寸变体 */
.nebula-button.small {
  padding: 8px 16px;
  font-size: 14px;
  min-width: 80px;
}

.nebula-button.medium {
  padding: 12px 24px;
  font-size: 16px;
  min-width: 120px;
}

.nebula-button.large {
  padding: 16px 32px;
  font-size: 18px;
  min-width: 160px;
}

/* 变体样式 */
.nebula-button.primary {
  background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
  color: white;
}

.nebula-button.secondary {
  background: linear-gradient(135deg, #1e1e2f, #292941);
  color: var(--primary-color);
  border: 1px solid var(--primary-color);
}

.nebula-button.outline {
  background: transparent;
  color: var(--primary-color);
  border: 2px solid var(--primary-color);
  box-shadow: none;
}

.nebula-button.text {
  background: transparent;
  color: var(--primary-color);
  border: none;
  box-shadow: none;
}

/* 禁用状态 */
.nebula-button.disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
}

/* 脉冲效果 */
.nebula-button.pulsing::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  transform: translate(-50%, -50%);
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0% {
    width: 0;
    height: 0;
    opacity: 0.8;
  }
  100% {
    width: 300px;
    height: 300px;
    opacity: 0;
  }
}

/* 悬停和点击效果 */
.nebula-button:not(.disabled):not(.loading):hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(85, 136, 255, 0.4);
}

.nebula-button:not(.disabled):not(.loading):active {
  transform: translateY(0);
}

.nebula-button.outline:not(.disabled):not(.loading):hover {
  background: rgba(85, 136, 255, 0.1);
}

.nebula-button.text:not(.disabled):not(.loading):hover {
  background: rgba(85, 136, 255, 0.1);
}

/* 加载状态 */
.loading-spinner {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 16px;
  min-height: 16px;
}

.spinner {
  width: 16px;
  height: 16px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top: 2px solid white;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* 图标样式 */
.button-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1em;
}

.button-icon.left-icon {
  margin-right: 8px;
}

.button-icon.right-icon {
  margin-left: 8px;
}

/* 图标调整 */
.nebula-button.has-icon.small .button-icon {
  font-size: 0.8em;
}

.nebula-button.has-icon.large .button-icon {
  font-size: 1.2em;
}

/* 文本样式 */
.button-text {
  display: inline-block;
  text-align: center;
}

.button-text.has-icons {
  margin: 0 4px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .nebula-button.small {
    padding: 6px 12px;
    font-size: 13px;
  }
  
  .nebula-button.medium {
    padding: 10px 20px;
    font-size: 14px;
  }
  
  .nebula-button.large {
    padding: 14px 28px;
    font-size: 16px;
    width: 100%;
  }
}
</style>